﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition.Primitives;
using System.Linq;
using Com.Lancetinc.Evs.Data.Domain;
using Com.Lancetinc.Evs.Helpers;

namespace Com.Lancetinc.Evs.Data.Repository
{
    public class ExperRepository : CrudRepository<Exper>
    {
        public ExperRepository()
            : base("SeqNo")
        {
        }

        public Exper FindBySeqNo(string seqNo)
        {
            return ExecuteWithoutTrans(cmd => FindByKey(cmd, seqNo));
        }

        public string FindMaxSeqNo(string seqNoPrefix)
        {
            return ExecuteWithoutTrans(cmd =>
            {
                cmd.CommandText = "select max(SeqNo) from Exper where SeqNo like '" + seqNoPrefix + "%'";
                var ret = cmd.ExecuteScalar();
                return ret is DBNull ? null : (string)ret;
            });
        }

        public int DeleteBySeqNo(string seqNo)
        {
            return ExecuteWithTrans(cmd =>
            {
                cmd.CommandText = "delete from Exper where SeqNo = '" + seqNo + "'";
                return cmd.ExecuteNonQuery();
            });
        }

        public void Save(Exper exper)
        {
            lock (exper)
            {
                ExecuteWithTrans(cmd =>
                {
                    if (UpdateByKey(cmd, exper) == 0)
                    {
                        Insert(cmd, exper);
                    }

                    return 1;
                });
            }
        }

        /// <summary>
        /// 批量导入实验文件
        /// </summary>
        /// <param name="expers">要导入的实验数据</param>
        /// <param name="seqNosToDel">导入前需要删除的数据</param>
        public void BatchImport(Exper[] expers, string[] seqNosToDel)
        {
            ExecuteWithTrans(cmd =>
            {
                if (seqNosToDel is { Length: > 0 })
                {
                    var inSql = string.Join(",", seqNosToDel.Select(x => $"'{x}'"));
                    cmd.CommandText = $"delete from Exper where SeqNo in ({inSql})";
                    cmd.ExecuteNonQuery();
                }

                Insert(cmd, expers);
                return expers.Length;
            });
        }

        /// <summary>
        /// 检查实验是否已存在
        /// </summary>
        /// <param name="seqNos"></param>
        /// <returns>返回已存在的流水号</returns>
        public string[] CheckExists(string[] seqNos)
        {
            return ExecuteWithoutTrans(cmd =>
            {
                var sqlSeqNos = string.Join(",", seqNos.Select(x => $"'{x}'"));
                cmd.CommandText = $"select SeqNo from Exper where SeqNo in ({sqlSeqNos})";
                var expers = FindList(cmd);
                return expers.Select(x => x.SeqNo).ToArray();
            });
        }

        /// <summary>
        /// 部分更新实验数据
        /// </summary>
        /// <param name="exper"></param>
        /// <param name="columns"></param>
        public void UpdatePartial(Exper exper, params string[] columns)
        {
            ExecuteWithTrans(cmd =>
            {
                UpdateByKey(cmd, exper, columns.Contains);
                return 1;
            });
        }

        /// <summary>
        /// 更新打印次数
        /// </summary>
        /// <param name="seqNo"></param>
        /// <param name="newCount">打印次数</param>
        /// <param name="printTime"></param>
        public void UpdatePrintCount(string seqNo, int newCount, DateTime? printTime = null)
        {
            printTime ??= DateTime.Now;
            var exper = new Exper
            {
                SeqNo = seqNo,
                LastPrintTime = printTime.Value.FormatForDbUpdate(),
                PrintCount = newCount
            };

            var columns = new[]
            {
                nameof(Exper.PrintCount),
                nameof(Exper.LastPrintTime)
            };
            UpdatePartial(exper, columns);
        }

        /// <summary>
        /// 分页搜索
        /// </summary>
        /// <param name="conds">搜索条件</param>
        /// <param name="pageNo">第X页,从1开始</param>
        /// <param name="pageSize">每页件数</param>
        /// <param name="totalCount">搜索总件数</param>
        /// <param name="orderByClause"></param>
        /// <returns></returns>
        public PagingInfo<Exper> QueryPage(SqlCondItem[] conds, int pageNo, int pageSize, int totalCount = -1, string orderByClause = null)
        {
            return ExecuteWithoutTrans(cmd =>
            {
                if (totalCount < 0)
                    totalCount = Count(cmd, conds);

                List<Exper> list;
                if (totalCount > 0)
                {
                    var offset = (pageNo - 1) * pageSize;
                    orderByClause = orderByClause ?? "StartTime desc,SeqNo desc";
                    list = FindList(cmd, conds, orderByClause, pageSize, offset);
                }
                else
                {
                    list = new List<Exper>();
                }

                return new PagingInfo<Exper>
                {
                    List = list,
                    PageNo = pageNo,
                    PageSize = pageSize,
                    TotalCount = totalCount
                };
            });
        }

        public IEnumerable<Exper> List(SqlCondItem[] conds)
        {
            return ExecuteWithoutTrans(cmd => FindList(cmd, conds, "StartTime desc,SeqNo desc"));
        }
    }
}